package spring.security.jwt;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.StreamUtils;
import spring.security.certs.CertProperties;
import spring.security.certs.RSACoder;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.util.Map;


@Configuration
@EnableConfigurationProperties({CertProperties.class})
public class JwtTokenConfig {

    private static KeyPair KEY_PAIR;

    @Autowired
    private CertProperties certProperties;

    private Logger logger= LoggerFactory.getLogger(JwtTokenConfig.class);


    @Bean
    public TokenStore jwtTokenStore(){
        JwtTokenStore jwtTokenStore=  new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
        Map<String,Object> keyMap=null;
        byte[] certFileBytes=null;
        try{
            URL url = new URL(certProperties.getFileStorePath());
            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
            //设置超时间为3秒
            connection.setConnectTimeout(30*1000);
            connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            certFileBytes=StreamUtils.copyToByteArray(connection.getInputStream());
            connection.disconnect();
        }catch (Exception ex){
            logger.error(certProperties.getFileStorePath()+" load fail",ex);
        }
        if(certProperties.getCertFileSuffix().endsWith("pfx")){
            try {
                keyMap=RSACoder.initKey(new ByteArrayInputStream(certFileBytes),certProperties.getPassword());
            } catch (Exception ex) {
                logger.error(certProperties.getFileStorePath()+" get fail",ex);
            }
        }
        accessTokenConverter.setKeyPair(new KeyPair((PublicKey) keyMap.get(RSACoder.PUBLIC_KEY),(PrivateKey) keyMap.get(RSACoder.PRIVATE_KEY)));
        return accessTokenConverter;
    }

    @Bean
    @Primary
    public ResourceServerTokenServices resourceJwtTokenServices() {
        final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        // 使用自定义的Token转换器
        defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
        // 使用自定义的tokenStore
        defaultTokenServices.setTokenStore(jwtTokenStore());
        return defaultTokenServices;
    }

    /**
     * token信息扩展
     */
    @Bean
    public TokenEnhancer jwtTokenEnhancer() {
        return new TokenEnhancer() {
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                Authentication userAuthentication = authentication.getUserAuthentication();
                if (userAuthentication != null) {
                    String userName = userAuthentication.getName();
//                    UserDetails userDetails=jwtService().loadUserByUsername(userName);
//                    if (userDetails != null) {
////                        SystemAccount account = list.get(0);
//                        Map<String, Object> additionalInformation = new HashMap<>();
//                        Map<String, String> map = new HashMap<>();
//                        map.put("account", userDetails.getUsername());
////                        map.put("createTime", new Date());
////                        map.put("state", String.valueOf(account.getState()));
//                        ObjectMapper objectMapper=new ObjectMapper();
//                        try {
//                            additionalInformation.put("user", objectMapper.writeValueAsString(map));
//                        } catch (JsonProcessingException e) {
//                            e.printStackTrace();
//                        }
//                        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
//                    }
                }
                return accessToken;
            }
        };
    }









}
